package com.tian.generator.service.impl;

import com.tian.generator.domain.*;
import com.tian.generator.mapper.GenMapper;
import com.tian.generator.service.IGenService;
import com.tian.generator.util.GenUtils;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Service
public class GenServiceImpl implements IGenService {
    private static final Logger logger = LogManager.getLogger(GenServiceImpl.class);
    private static String path = new File(GenServiceImpl.class.getClassLoader().getResource("ftls").getFile()).getPath();
    @Autowired
    private GenMapper genMapper;

    /**
     * 查询ry数据库表信息
     *
     * @param tableInfo 表信息
     * @return 数据库表列表
     */
    @Override
    public List<TableInfo> selectTableList(TableInfo tableInfo) {
        return genMapper.selectTableList(tableInfo);
    }

    /**
     * 生成代码
     *
     * @param tableName 表名称
     * @return 数据
     */
    @Override
    public byte[] generatorCode(String tableName) throws IOException, TemplateException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        // 查询表信息
        TableInfo table = genMapper.selectTableByName(tableName);
        // 查询列信息
        List<ColumnInfo> columns = genMapper.selectTableColumnsByName(tableName);
        // 生成代码
        generatorCode(table, columns, zip);
        IOUtils.closeQuietly(zip);
        return outputStream.toByteArray();
    }

    /**
     * 批量生成代码
     *
     * @param tableNames 表数组
     * @return 数据
     */
    @Override
    public byte[] generatorCode(String[] tableNames) throws IOException, TemplateException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        for (String tableName : tableNames) {
            // 查询表信息
            TableInfo table = genMapper.selectTableByName(tableName);
            // 查询列信息
            List<ColumnInfo> columns = genMapper.selectTableColumnsByName(tableName);
            // 生成代码
            generatorCode(table, columns, zip);
        }
        IOUtils.closeQuietly(zip);
        return outputStream.toByteArray();
    }

    /**
     * 生成代码
     */
    public void generatorCode(TableInfo table, List<ColumnInfo> columns, ZipOutputStream zip) {
        //配置model数据
        List<ColumnJava> listColumn = GenUtils.columsToJava(columns);
        TableJava tableJava = GenUtils.tableToJava(table, listColumn);
        CollectJava collectJava = GenUtils.getCollectJava(tableJava);
        // 获取模板列表
        List<String> templates = GenUtils.getTemplates();
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_29);
        for (String template : templates) {
            try {
                // 渲染模板
                cfg.setDirectoryForTemplateLoading(new File(path));
                // java对象数据传递到模板文件ftl
                Template tpl = cfg.getTemplate(template, "UTF-8");
                // 填充数据
                StringWriter writer = new StringWriter();
                tpl.process(collectJava, writer);
                // 添加到zip
                zip.putNextEntry(new ZipEntry(GenUtils.getFileName(template, collectJava)));
                IOUtils.write(writer.toString(), zip, "UTF-8");
                IOUtils.closeQuietly(writer);
                zip.closeEntry();
            } catch (IOException e) {
                logger.error("渲染模板失败，表名：" + table.getTableName(), e);
            } catch (TemplateException e) {
                logger.error("渲染模板失败，表名：" + table.getTableName(), e);
            }
        }
    }
}
